from docx import Document
from docx.shared import Pt, Cm
from docx.oxml.ns import qn
import re

class ToWordDocument:
    def __init__(self):
        """
        初始化方法，自动设置文档格式
        """
        self.doc = Document()
        self.content = ""  # 用于存储读取的文本内容
        self.set_format()  # 初始化时自动设置格式
    
    def set_format(self):
        """
        设置文档格式：
        - 页边距：1cm
        - 字体：汉仪润圆-75W
        - 字号：四号(14磅)
        - 行间距：固定值16磅
        - 段前段后间距：0磅
        """
        # 设置页边距
        for section in self.doc.sections:
            section.top_margin = Cm(1)
            section.bottom_margin = Cm(1)
            section.left_margin = Cm(1)
            section.right_margin = Cm(1)
        
        # 设置字体和字号
        style = self.doc.styles['Normal']
        style.font.name = '汉仪润圆-75W'
        style._element.rPr.rFonts.set(qn('w:eastAsia'), '汉仪润圆-75W')
        style.font.size = Pt(14)  # 四号字
        
        # 设置段落格式
        paragraph_format = style.paragraph_format
        paragraph_format.line_spacing = Pt(16)  # 固定值16磅
        paragraph_format.space_before = Pt(0)   # 段前0磅
        paragraph_format.space_after = Pt(0)    # 段后0磅
    
    def read_book(self, txt_path):
        """
        从txt文件读取内容并存储在变量中
        :param txt_path: 要读取的txt文件路径
        """
        try:
            with open(txt_path, 'r', encoding='utf-8') as file:
                self.content = file.read()
            print(f"已成功读取文件: {txt_path}")
        except Exception as e:
            print(f"读取文件失败: {e}")
            self.content = ""
    
    def organise_content(self):
        """
        查找所有最外层{{}}内容并组织处理信息
        处理嵌套情况，只匹配最外层{{}}
        """
        if not self.content:
            print("警告: 没有可处理的内容")
            return
        
        stack = []
        matches_info = []
        i = 0
        n = len(self.content)
        
        while i < n:
            if self.content.startswith('{{', i):
                # 遇到开括号，压栈
                stack.append(i)
                i += 2  # 跳过'{{'
            elif self.content.startswith('}}', i) and stack:
                # 遇到闭括号且栈不为空
                start = stack.pop()
                # 如果栈为空，说明是最外层
                if not stack:
                    full_text = self.content[start:i+2]
                    inner_text = self.content[start+2:i].strip()
                    parts = [part.strip() for part in inner_text.split('|')]
                    tag = parts[0] if len(parts) > 0 else ""
                    
                    matches_info.append({
                        'start': start,
                        'end': i+2,
                        'full_text': full_text,
                        'tag': tag,
                        'parts': parts
                    })
                i += 2  # 跳过'}}'
            else:
                i += 1
        
        # 从后往前处理，避免索引变化影响
        for info in reversed(matches_info):
            if info['tag'] == '折叠':
                self.content = self.deal_zd(info)
            elif info['tag'] == '图片放大':
                self.content = self.deal_tpfz(info)
            elif info['tag'] == '任务':
                self.content = self.deal_rw(info)
            elif info['tag'] == '短信选项':
                self.content = self.deal_dxxx(info)
            elif info['tag'] == '提示':
                self.content = self.deal_ts(info)
            elif info['tag'] == '剧情选项':
                self.content = self.deal_jqxx(info)
            elif info['tag'] == '黑幕':
                self.content = self.deal_hm(info)
            elif info['tag'] == '角色对话':
                self.content = self.deal_jsdh(info)
            elif info['tag'] == '提示消息':
                self.content = self.deal_tsxx(info)
            elif info['tag'] == '任务描述':
                self.content = self.deal_rwms(info)
            elif info['tag'] == '短信警告':
                self.content = self.deal_dxjg(info)
            elif info['tag'] == '颜色':
                self.content = self.deal_ys(info)
            elif info['tag'] == '注音':
                self.content = self.deal_zy(info)
            elif info['tag'] == '图标':
                self.content = self.deal_tb(info)
            elif info['tag'] == '事件':
                self.content = self.deal_sj(info)
            else:
                # 默认处理方式
                self.content = self.deal_default(info)

    # 以下是所有新增的处理函数
    def deal_zd(self, info):
        """
        处理折叠内容
        格式: {{折叠|标题|内容}}
        处理要求:
        1. 提取标题和内容
        2. 生成可折叠的HTML结构
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 3:
            title = parts[1]
            content = parts[2]
            new_text = f"<details><summary>{title}</summary>{content}</details>"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_tpfz(self, info):
        """
        处理图片放大内容
        格式: {{图片放大|图片URL|描述文字}}
        处理要求:
        1. 提取图片URL和描述
        2. 生成带点击放大功能的图片标签
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 3:
            img_url = parts[1]
            description = parts[2]
            new_text = f"""
            <div class="image-zoom-container">
                <img src="{img_url}" alt="{description}" class="zoomable-image">
                <p class="image-caption">{description}</p>
            </div>
            """
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_dxxx(self, info):
        """
        处理短信选项内容
        格式: {{短信选项|选项1|回复1|选项2|回复2|...}}
        处理要求:
        1. 提取选项和对应回复
        2. 生成交互式短信界面
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) > 1 and len(parts) % 2 == 1:
            new_text = "<div class='sms-interface'>\n"
            for i in range(1, len(parts), 2):
                option = parts[i]
                reply = parts[i+1]
                new_text += f"  <div class='sms-option' data-reply='{reply}'>{option}</div>\n"
            new_text += "</div>"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_jqxx(self, info):
        """
        处理剧情选项内容
        格式: {{剧情选项|选项1|剧情1|选项2|剧情2|...}}
        处理要求:
        1. 提取选项和对应剧情
        2. 生成分支选择界面
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) > 1 and len(parts) % 2 == 1:
            new_text = "<div class='plot-options'>\n"
            for i in range(1, len(parts), 2):
                option = parts[i]
                plot = parts[i+1]
                new_text += f"  <div class='plot-option' data-plot='{plot}'>{option}</div>\n"
            new_text += "</div>"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_jsdh(self, info):
        """
        处理角色对话内容
        格式: {{角色对话|角色名|对话内容}}
        处理要求:
        1. 根据角色名应用不同样式
        2. 处理对话中的特殊标记
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 3:
            character = parts[1]
            dialogue = parts[2]
            new_text = f"<div class='dialogue {character.lower()}'><span class='character'>{character}:</span> {dialogue}</div>"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_rwms(self, info):
        """
        处理任务描述内容
        格式: {{任务描述|描述内容|地点}}
        处理要求:
        1. 生成带地点的任务描述块
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 3:
            description = parts[1]
            location = parts[2]
            new_text = f"<div class='quest-desc'><p>{description}</p><p class='location'>{location}</p></div>"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_dxjg(self, info):
        """
        处理短信警告内容
        格式: {{短信警告|内容}}
        处理要求:
        1. 生成警告样式的短信界面
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 2:
            content = parts[1]
            new_text = f"<div class='sms-warning'>{content}</div>"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_zy(self, info):
        """
        处理注音内容
        格式: {{注音|文字|拼音}}
        处理要求:
        1. 生成带拼音标注的文字
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 3:
            text = parts[1]
            pinyin = parts[2]
            new_text = f"<ruby>{text}<rt>{pinyin}</rt></ruby>"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    # 以下是原始文件中已有的处理函数
    def deal_sj(self, info):
        """
        处理"事件"标签内容
        1. 以'|'分割内容，将除第一部分外的其他部分用'|'拼接
        2. 新建处理器处理拼接后的内容
        3. 格式化为：-|事件| ：处理后的内容
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']

        if len(parts) >= 2:
            combined_content = '|'.join(parts[1:])
            sub_processor = ToWordDocument()
            sub_processor.content = combined_content
            sub_processor.organise_content()
            new_text = f"-|事件| ：{sub_processor.content}"
        else:
            new_text = ''

        content_list[start:end] = list(new_text)
        return ''.join(content_list)

    def deal_tsxx(self, info):
        """
        处理"提示消息"标签内容
        格式化为：-|第二部分|提示| ：修改后的第三部分
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']

        if len(parts) >= 3:
            third_part = parts[2].replace("'''", "").replace("<br>", "\n").strip()
            new_text = f"-|{parts[1]}|提示| ：{third_part}"
        else:
            new_text = ''

        content_list[start:end] = list(new_text)
        return ''.join(content_list)
    
    def deal_ts(self, info):
        """
        处理"提示"标签内容并返回处理后的完整内容
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 1 and parts[-1] == '如果选择选项下面对话没变不是BUG了，而是游戏本身对话就是一样的。':
            content_list[start:end] = ['']
        elif len(parts) >= 3:
            new_text = '|'.join(parts[3:]).strip().replace('<br>', '\n').replace('|', '：')
            content_list[start:end] = list(new_text)
        else:
            content_list[start:end] = ['']
            
        return ''.join(content_list)
    
    def deal_tb(self, info):
        """
        处理"图标"标签内容并返回处理后的完整内容
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 3:
            new_text = f"{parts[1]}*{parts[2]}"
        elif len(parts) >= 2:
            new_text = f"{parts[1]}*1"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)
    
    def deal_hm(self, info):
        """
        处理"黑幕"标签内容并返回处理后的完整内容
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 2:
            new_text = f"(黑幕:{parts[1]})"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)
    
    def deal_ys(self, info):
        """
        处理"颜色"标签内容并返回处理后的完整内容
        """
        content_list = list(self.content)
        start, end = info['start'], info['end']
        parts = info['parts']
        
        if len(parts) >= 3:
            sub_processor = ToWordDocument()
            sub_processor.content = parts[2]
            sub_processor.organise_content()
            new_text = f"-|{parts[1]}| ：{sub_processor.content}"
        else:
            new_text = ''
        
        content_list[start:end] = list(new_text)
        return ''.join(content_list)
    
    def deal_default(self, info):
        """
        默认处理函数，对未识别的标签不做处理
        """
        return self.content
    
    def save_word(self, output_path):
        """
        将存储的内容添加到Word文档并保存
        :param output_path: 输出的Word文档路径
        """
        if not self.content:
            print("警告: 没有可保存的内容，请先调用read_book方法读取内容")
            return
        
        try:
            paragraph = self.doc.add_paragraph()
            paragraph.add_run(self.content)
            self.doc.save(output_path)
            print(f"Word文档已成功保存至: {output_path}")
        except Exception as e:
            print(f"保存Word文档失败: {e}")

# 使用示例
if __name__ == "__main__":
    converter = ToWordDocument()
    converter.read_book('1混乱行至深处.txt')
    converter.organise_content()
    converter.save_word('混乱行至深处.docx')